#include "FunTrace.h"
#include <http.h>
#include "publictransportsg.h"
#include <aknglobalnote.h> 
#include <aknnotewrappers.h> 

static void PrintNoteL(TRefByValue<const TDesC> aFormat, ...)
    {
    VA_LIST list;
    VA_START(list, aFormat);
    TBuf<256> buf;
    buf.FormatList(aFormat, list);
    VA_END(list);
	CAknGlobalNote* globalNote = CAknGlobalNote::NewLC();
	globalNote->ShowNoteL(EAknGlobalInformationNote, buf); 
    CleanupStack::PopAndDestroy(globalNote);
    }

static void SetHeaderL(RHTTPSession& aSession, RHTTPHeaders aHeaders, TInt aHdrField, const TDesC8& aHdrValue)
  {
	RStringF valStr = aSession.StringPool().OpenFStringL(aHdrValue);
	CleanupClosePushL(valStr);
	THTTPHdrVal val(valStr);
	aHeaders.SetFieldL(aSession.StringPool().StringF(aHdrField,
		RHTTPSession::GetTable()), val);
	CleanupStack::PopAndDestroy();  // valStr
  }

// ================
// ================
// ================
void CPublicTransportRequestBusarrivaltime::ConstructL()
{
TFunTrace funTrace(__PRETTY_FUNCTION__);
	iStop = NULL;
	iBody.CreateL(4096);
	iTransactionSubmitted = EFalse;
}

CPublicTransportRequestBusarrivaltime* CPublicTransportRequestBusarrivaltime::NewLC()
{
TFunTrace funTrace(__PRETTY_FUNCTION__);
	CPublicTransportRequestBusarrivaltime* ret = new (ELeave) CPublicTransportRequestBusarrivaltime;
	CleanupStack::PushL(ret);
	ret->ConstructL();
	return ret;
}

CPublicTransportRequestBusarrivaltime* CPublicTransportRequestBusarrivaltime::NewL()
{
TFunTrace funTrace(__PRETTY_FUNCTION__);
	CPublicTransportRequestBusarrivaltime* ret = NewLC();
	CleanupStack::Pop(ret);
	return ret;
}

void CPublicTransportRequestBusarrivaltime::SubmitL(RHTTPSession& aSession, const TDesC8& aStop, MPublicTransportCallbackBusarrivaltime* aTarget)
	{
TFunTrace funTrace(__PRETTY_FUNCTION__);
	delete iStop;
	iStop = aStop.AllocL();
	iTarget = aTarget;
	iSession = &aSession;
	
	RBuf8 uristr;
	CleanupClosePushL(uristr);
	uristr.CreateL(1024);
	uristr.AppendFormat(_L8("http://www.publictransport.sg/publish/mobile/en/busarrivaltime.jsp?submit=submit&bus_stop=%S"), iStop);
	TUriParser8 uri;
	uri.Parse( uristr );
	RStringF method = iSession->StringPool().StringF(HTTP::EGET,RHTTPSession::GetTable());
	CleanupClosePushL(method);
	iTransaction.Close();
	iTransaction = iSession->OpenTransactionL(uri, *this, method);

	{
		// server does not support pipelining
		RStringPool strP = iSession->StringPool();
		const TStringTable& stringTable = RHTTPSession::GetTable();
		RStringF httpPipelining = strP.StringF( HTTP::EHttpPipelining, stringTable );
		THTTPHdrVal disablePipelining = strP.StringF( HTTP::EDisablePipelining, stringTable );
		iTransaction.PropertySet().RemoveProperty( httpPipelining );
		iTransaction.PropertySet().SetPropertyL( httpPipelining, disablePipelining );
	}
	
	iBody.Zero();
	iLastError = KErrNone;
	iTransaction.SubmitL();
	iTransactionSubmitted = ETrue;
	CleanupStack::PopAndDestroy(&method);
	CleanupStack::PopAndDestroy(&uristr);
	}

TBool CPublicTransportRequestBusarrivaltime::RequestPending() const
	{
TFunTrace funTrace(__PRETTY_FUNCTION__);
	return iTransactionSubmitted;
	}

void CPublicTransportRequestBusarrivaltime::Cancel()
	{
	if(iTransactionSubmitted)
		iTransaction.Cancel();
	iTransaction.Close();
	iTransactionSubmitted = EFalse;
	}

CPublicTransportRequestBusarrivaltime::~CPublicTransportRequestBusarrivaltime()
{
	delete iStop;
	iTransaction.Close();
	iBody.Close();
}

static TInt Locate2(const TDesC8& aDesC, TChar aChar1, TChar aChar2)
	{
	TInt ret;
	for(ret = 0 ; ret < aDesC.Length() && !(aDesC[ret] == aChar1 || aDesC[ret] == aChar2) ; ++ret);
	if(ret == aDesC.Length()) ret = KErrNotFound;
	return ret;
	}



void CPublicTransportRequestBusarrivaltime::MHFRunL(RHTTPTransaction aTransaction, const THTTPEvent& aEvent)
	{
TFunTrace funTrace(__PRETTY_FUNCTION__);
if(aEvent.iStatus < KErrNone) iLastError = aEvent.iStatus;
	  switch (aEvent.iStatus)
	    {
			case THTTPEvent::EUnrecoverableError:
				iLastError = KErrNotReady; // for Symbian 5th ed + 
			  break;
	    case THTTPEvent::EGotResponseHeaders:
	      break;

	    case THTTPEvent::EGotResponseBodyData:
	    	{
		      MHTTPDataSupplier* body = aTransaction.Response().Body();
		      TPtrC8 part;	      
		      body->GetNextDataPart(part);
		      if(part.Length() + iBody.Length() > iBody.MaxLength() )
		    	  iBody.ReAllocL(part.Length() + iBody.Length());	    	  	    	  
	    	  iBody.Append(part);	    	  	    	  
		      body->ReleaseData();
	    	}		      
	      break;

	    case THTTPEvent::ESucceeded:
	    case THTTPEvent::EFailed:
	    	TInt statusCode = aTransaction.Response().StatusCode();
	    	Cancel();
			
			HBufC8* savStop = iStop;
			iStop = NULL;
			struct{ } iStop, iService; // to "remove" the variables from the scope
			CleanupStack::PushL(savStop);
			
			if(aEvent.iStatus == THTTPEvent::ESucceeded)
				{
		    	_LIT8(kPrefix, "<td align=\"left\">");

		    	TPtrC8 svcrow = iBody;
		    	TInt begsvcrow, nextsvcrow;
		    	TInt svcrowindex = 0;
		    	for(begsvcrow = svcrow.Find(kPrefix), svcrowindex = 0 ; begsvcrow != KErrNotFound ; begsvcrow = nextsvcrow, ++svcrowindex)
		    		{
					svcrow.Set( svcrow.Mid(begsvcrow) );
					TPtrC8 field[3];
					TInt begtd = 0, nexttd;
					for(TInt i = 0 ; i < 3 ; ++i, begtd = nexttd)
						{
						const TInt begfield = begtd + 1 + User::LeaveIfError( svcrow.Mid(begtd).Locate('>') );
			    		const TInt endfield = begfield + User::LeaveIfError( Locate2(svcrow.Mid(begfield), '<', '&') );
			    		const TInt nexttd_endfield = svcrow.Mid(endfield).Find(kPrefix);
			    		nexttd = (nexttd_endfield != KErrNotFound) ? endfield + nexttd_endfield : KErrNotFound;
			    		field[i].Set( svcrow.Mid(begfield, endfield - begfield) );
			    		}
					nextsvcrow = nexttd;				
					iTarget->MPublicTransportCallbackBusarrivaltimeRunL(*savStop, aEvent.iStatus, iLastError, statusCode, field[0], field[1], field[2], svcrowindex);
					}
				}
			iTarget->MPublicTransportCallbackBusarrivaltimeRunL(*savStop, aEvent.iStatus, iLastError, statusCode, KNullDesC8, KNullDesC8, KNullDesC8, -1);
			
			CleanupStack::PopAndDestroy(savStop);
			
			
	      break;

	    case THTTPEvent::ERedirectedPermanently:
	      break;
	    	
	    case THTTPEvent::ERedirectedTemporarily:
	      break;
	    	
	    default:
	      break;
	    }
	}
TInt CPublicTransportRequestBusarrivaltime::MHFRunError(TInt aError, RHTTPTransaction aTransaction, const THTTPEvent& aEvent)
	{
TFunTrace funTrace(__PRETTY_FUNCTION__);
	}

